<template>
    <div class="resume-container">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
            <h2>简历详情</h2>
            <!-- <el-button type="primary" size="small" @click="enableRefinement = true">
                简历润色
            </el-button> -->
        </div>
        <!-- 简历解析信息 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;"><i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>简历信息</h3>
            </div>
            <el-row :gutter="20" style="margin-top: 10px;">
                <el-col :span="8"><span class="dot"></span>简历类型：{{ getResumeTypeName(resumeData.result.resume_type)
                    }}</el-col>
                <el-col :span="8"><span class="dot"></span>完整度：{{ resumeData.result.resume_integrity }}</el-col>
                <el-col :span="8"><span class="dot"></span>解析时间：{{ resumeData.result.resume_parse_time }}</el-col>
            </el-row>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 教育信息 -->
        <!-- 教育经历 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;">
                <i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>教育经历</h3>
            </div>
            <div v-for="(edu, index) in resumeData.result.education_objs" :key="index" style="margin-top: 10px;">
                <p>
                    <span class="dot"></span>{{ edu.start_date }} ~ {{ edu.end_date }}
                    {{ edu.edu_college }}（{{ getCollegeTypeName(edu.edu_college_type) }}，国内排名 {{ edu.edu_college_rank
                    }}，国际排名 {{ edu.edu_college_rank_qs }}）
                </p>
                <p>
                    <span class="dot"></span>{{ edu.edu_major }} | {{ edu.edu_degree }}
                </p>
                <el-button size="mini" type="info" :disabled="refinementLoading.education[index]"
                    @click="refineSection('education', index, edu.edu_major + '，' + edu.edu_degree + '，' + edu.edu_college)">
                    {{ refinementLoading.education[index] ? '正在生成润色建议，请稍等' : '润色建议' }}
                </el-button>
                <!-- <el-button v-if="enableRefinement" size="mini" type="info"
                    @click="refineSection('education', index, edu.edu_major + '，' + edu.edu_degree + '，' + edu.edu_college)">润色建议</el-button> -->
                <el-card v-if="refinementResults.education[index]" class="refinement-card"
                    style="color: #0063A8; margin-top: 6px; overflow-x:auto;">
                    <el-table :data="refinementResults.education[index]" border stripe style="width: 100%;">
                        <el-table-column prop="原文" label="原文" min-width="30%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                        <el-table-column prop="润色建议" label="润色建议" min-width="35%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                        <el-table-column prop="理由/效果" label="理由/效果" min-width="35%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                    </el-table>
                </el-card>
            </div>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 联系方式 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;"><i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>联系方式</h3>
            </div>
            <p style="margin-top: 10px;"><i class="el-icon-message"></i> {{ resumeData.result.email }}</p>
            <p style="margin-top: 10px;"><i class="el-icon-phone"></i> {{ resumeData.result.phone }}</p>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 期望工作 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;"><i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>期望工作</h3>
            </div>
            <el-row :gutter="20" style="margin-top: 10px;">
                <el-col :span="8"><span class="dot"></span>行业：{{ resumeData.result.expect_industry }}</el-col>
                <el-col :span="8"><span class="dot"></span>职位：{{ resumeData.result.expect_job }}</el-col>
                <el-col :span="8"><span class="dot"></span>薪资：{{ resumeData.result.expect_salary }}</el-col>
            </el-row>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 工作经历 -->
        <!-- 工作经历 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;">
                <i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>工作经历</h3>
            </div>
            <div v-for="(job, index) in resumeData.result.job_exp_objs" :key="index" style="margin-top: 10px;">
                <p><strong>{{ job.start_date }} ~ {{ job.end_date }}</strong></p>
                <p><span class="dot"></span>{{ job.job_position }} @ {{ job.job_cpy }}（{{ job.job_industry }}，{{
                    job.job_cpy_size }}）</p>
                <p><span class="dot"></span>部门：{{ job.job_dept }} | 工作时长：{{ job.job_duration }}</p>
                <p style="line-height:1.5;"><span class="dot"></span>工作内容：{{ job.job_content }}</p>
                <!-- <el-button v-if="enableRefinement" size="mini" type="info" -->
                <!-- @click="refineSection('job', index, job.job_content)">润色建议</el-button> -->
                <el-button size="mini" type="info" :disabled="refinementLoading.job[index]"
                    @click="refineSection('job', index, job.job_content)">
                    {{ refinementLoading.job[index] ? '正在生成润色建议，请稍等' : '润色建议' }}
                </el-button>
                <el-card v-if="refinementResults.job[index]" class="refinement-card"
                    style="color: #0063A8; margin-top: 6px; overflow-x:auto;">
                    <el-table :data="refinementResults.job[index]" border stripe style="width: 100%;">
                        <el-table-column prop="原文" label="原文" min-width="30%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                        <el-table-column prop="润色建议" label="润色建议" min-width="35%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                        <el-table-column prop="理由/效果" label="理由/效果" min-width="35%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                    </el-table>
                </el-card>
            </div>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 项目经历 -->
        <div class="box-card" shadow="always" style="margin-top: 20px;">
            <div style="display: flex;">
                <i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>项目经历</h3>
            </div>
            <div v-for="(project, index) in resumeData.result.proj_exp_objs" :key="index" style="margin-top: 10px;">
                <p><strong>{{ project.start_date }} ~ {{ project.end_date }}</strong></p>
                <p><span class="dot"></span>项目信息：名称：{{ project.proj_name }}<span v-if="project.proj_position"> | 职位：{{
                    project.proj_position }}</span></p>
                <p><span class="dot"></span>项目描述：{{ project.proj_content }}</p>
                <!-- <el-button v-if="enableRefinement" size="mini" type="info" -->
                <!-- @click="refineSection('project', index, project.proj_content)">润色建议</el-button> -->
                <el-button size="mini" type="info" :disabled="refinementLoading.project[index]"
                    @click="refineSection('project', index, project.proj_content)">
                    {{ refinementLoading.project[index] ? '正在生成润色建议，请稍等' : '润色建议' }}
                </el-button>
                <el-card v-if="refinementResults.project[index]" class="refinement-card"
                    style="color: #0063A8; margin-top: 6px; overflow-x:auto;">
                    <el-table :data="refinementResults.project[index]" border stripe style="width: 100%;">
                        <el-table-column prop="原文" label="原文" min-width="30%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                        <el-table-column prop="润色建议" label="润色建议" min-width="35%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                        <el-table-column prop="理由/效果" label="理由/效果" min-width="35%"
                            :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                    </el-table>
                </el-card>
            </div>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 培训经历 -->
        <div class="box-card" shadow="always" style="margin-top: 20px" v-if="resumeData.result.training_objs.length">
            <div style="display: flex;"><i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>培训经历</h3>
            </div>
            <div v-for="(train, index) in resumeData.result.training_objs" :key="index" style="margin-top: 10px;">
                <p><span class="dot"></span>机构：{{ train.train_org }}</p>
                <p><span class="dot"></span>内容：{{ train.train_cont }}</p>
            </div>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 证书与奖项 -->
        <div class="box-card" shadow="always" style="margin-top: 20px"
            v-if="resumeData.result.all_cert_objs && resumeData.result.all_cert_objs.length">
            <div style="display: flex;">
                <i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>证书与奖项</h3>
            </div>
            <div style="margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px;">
                <el-tag v-for="(cert, i) in resumeData.result.all_cert_objs" :key="i" type="primary" size="normal">
                    {{ cert.cert_type === 'award' ? '奖项' : cert.cert_type === 'certificate' ? '证书' : '其他' }} - {{
                        cert.cert_name }}
                </el-tag>
            </div>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 技能列表 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;">
                <i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>技能列表</h3>
            </div>
            <el-row :gutter="10" style="margin-top: 10px; text-align: left;">
                <el-col v-for="(skill, i) in resumeData.result.skills_objs" :key="i" :span="8"
                    style="line-height: 1.5;">
                    <span class="dot"></span>{{ skill.skills_name }}
                    <span v-if="skill.skills_level"> - {{ skill.skills_level }}</span>
                </el-col>
            </el-row>
        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 自我评价 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;">
                <i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>自我评价</h3>
            </div>
            <p style="white-space: pre-wrap; margin-top: 10px;">
                {{ resumeData.result.cont_my_desc }}
            </p>
            <!-- <el-button v-if="enableRefinement" size="mini" type="info" -->
            <!-- @click="refineSection('self', 0, resumeData.result.cont_my_desc)">润色建议</el-button> -->
            <el-button size="mini" type="info" :disabled="refinementLoading.self[0]"
                @click="refineSection('self', 0, resumeData.result.cont_my_desc)">
                {{ refinementLoading.self[0] ? '正在生成润色建议，请稍等' : '润色建议' }}
            </el-button>
            <el-card v-if="refinementResults.self[0]" class="refinement-card" style="margin-top: 6px; overflow-x:auto;">
                <el-table :data="refinementResults.self[0]" border stripe style="width: 100%;">
                    <el-table-column prop="原文" label="原文" min-width="30%"
                        :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                    <el-table-column prop="润色建议" label="润色建议" min-width="35%"
                        :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                    <el-table-column prop="理由/效果" label="理由/效果" min-width="35%"
                        :cell-style="{ whiteSpace: 'normal', wordBreak: 'break-word' }" />
                </el-table>
            </el-card>





        </div>

        <el-divider style="margin-top: 10px; margin-bottom: 10px;width:100%" />

        <!-- 个人技能 -->
        <div class="box-card" shadow="always" style="margin-top: 20px">
            <div style="display: flex;">
                <i class="el-icon-caret-right" style="color: rgb(255, 180, 54);"></i>
                <h3>个人技能</h3>
            </div>
            <p style="margin-top: 10px;line-height:1.5;">
                {{ resumeData.result.cont_job_skill }}
            </p>
        </div>

    </div>
</template>

<script>
import CryptoJS from 'crypto-js';  // Add this import
import { mapGetters } from 'vuex';

export default {
    name: 'resumeAnalyze',
    props: {
        resumeData: {
            type: Object,
            required: true
        }
    },
    mounted() {
        // 示例：可以在这里使用 this.resumeData
        console.log('简历解析数据：', this.resumeData);
    },
    data() {
        return {
            showTopPanel: true,
            activeTab: 'parser',
            selectedFile: null,
            base64FileContent: '',
            error: '',
            loading: false,
            formattedResult: '', // 用于展示的字符串（可选）
            resumeData: {
                status: {
                    message: '',
                    code: 0
                },
                result: {
                    name: '',
                    gender: '',
                    age: '',
                    marital_status: '',
                    polit_status: '',
                    major: '',
                    surname: '',
                    height: '',
                    weight: '',
                    birthday: '',
                    city_norm: '',
                    college: '',
                    college_type: '',
                    college_rank: '',
                    has_oversea_edu: '',
                    has_oversea_exp: '',
                    city: '',
                    grad_time: '',
                    degree: '',
                    race: '',
                    nationality: '',
                    english_level: '',
                    computer_level: '',
                    work_position: '',
                    work_company: '',
                    work_industry: '',
                    work_start_time: '',
                    work_year_norm: '',
                    work_year: '',
                    work_job_nature: '',
                    work_start_time_inf: '',
                    phone: '',
                    email: '',
                    postal_code: '',
                    qq: '',
                    weixin: '',
                    expect_salary: '',
                    expect_salary_min: '',
                    expect_salary_max: '',
                    expect_job: '',
                    expect_industry: '',
                    living_address: '',
                    living_address_norm: '',
                    hukou_address_norm: '',
                    hukou_address: '',
                    hometown_address_norm: '',
                    hometown_address: '',
                    resume_type: '',
                    resume_source: '',
                    resume_integrity: '',
                    resume_parse_time: '',
                    resume_name: '',
                    avatar_data: '',
                    education_objs: [
                        {
                            edu_college: '',
                            edu_major: '',
                            start_date: '',
                            end_date: '',
                            edu_degree: '',
                            edu_degree_norm: '',
                            edu_college_rank: '',
                            edu_college_type: ''
                        }
                    ],
                    job_exp_objs: [
                        {
                            job_position: '',
                            end_date: '',
                            job_content: '',
                            job_cpy: '',
                            job_industry: '',
                            job_cpy_size: '',
                            job_duration: '',
                            start_date: '',
                            job_dept: ''
                        }
                    ],
                    proj_exp_objs: [
                        {
                            proj_position: '',
                            proj_resp: '',
                            proj_name: '',
                            start_date: '',
                            end_date: ''
                        }
                    ],
                    training_objs: [
                        {
                            train_org: '',
                            train_cont: ''
                        }
                    ],
                    cert_objs: [
                        {
                            langcert_lang: '',
                            langcert_name: ''
                        }
                    ],
                    all_cert_objs: [
                        {
                            cert_type: '',
                            cert_name: ''
                        }
                    ],
                    lang_objs: [
                        {
                            language_name: ''
                        }
                    ],
                    skills_objs: [
                        {
                            skills_name: '',
                            skills_level: ''
                        }
                    ],
                    cont_basic_info: '',
                    cont_expect_job: '',
                    cont_education: '',
                    cont_job_exp: '',
                    cont_proj_exp: '',
                    cont_job_skill: '',
                    raw_text: ''
                },
                tags: {
                    industries: [
                        {
                            tag_weight: '',
                            tag_name: ''
                        }
                    ],
                    pos_types: [
                        {
                            tag_weight: '',
                            tag_name: ''
                        }
                    ],
                    pos_tags: [
                        {
                            tag_weight: '',
                            tag_name: ''
                        }
                    ],
                    skills_tags: [
                        {
                            tag_weight: '',
                            tag_name: ''
                        }
                    ]
                },
                eval: {
                    salary: ''
                }
            },
            enableRefinement: false,
            refinementLoading: {
                education: [],
                job: [],
                project: [],
                self: []
            },
            refinementResults: {
                education: {},
                job: {},
                project: {},
                self: {}
            },
            sections: [
                {
                    title: '教育经历',
                    content: '在清华大学计算机系完成本科学业，主修人工智能与数据科学，GPA 3.85/4.0。',
                    suggestion: ''
                },
                {
                    title: '工作经历',
                    content: '在字节跳动担任前端开发实习生，参与抖音 Web 端页面改版和性能优化。',
                    suggestion: ''
                },
                {
                    title: '项目经历',
                    content: '主导开发校园社交平台，基于 Vue 和 Node 构建，支持即时通讯、动态发布等功能，累计用户超 5 千人。',
                    suggestion: ''
                },
                {
                    title: '自我评价',
                    content: '具备扎实的计算机基础与较强的团队合作能力，热爱技术，愿意不断探索与学习。',
                    suggestion: ''
                },
            ],
            appId: 'e9f15e7b',
            apiSecret: 'YTk4MzhhOGY5MDNjNWI2ZjAzYjEwMWVi',
            apiKey: '8f4950aa42fdca8eac189b3edb74da82',
            wsHost: 'spark-api.xf-yun.com'
        }
    },
    computed: {
        refinementTableData() {
            const raw = this.refinementResults.self[0] || '';
            // 按行切分，并过滤空行，转成表格数组
            return raw.split('\n')
                .map(line => line.trim())
                .filter(line => line.length > 0)
                .map((line, index) => ({ index: index + 1, suggestion: line }));
        }
    },
    methods: {
        getCollegeTypeName(typeCode) {
            const typeMap = {
                '0': '普通院校',
                '1': '985',
                '2': '211',
                '3': '港澳台院校',
                '4': '海外院校',
                '5': '中学',
                '6': '职业教育',
                '7': '培训机构'
            };
            return typeMap[String(typeCode)] || '未知类型';
        },
        getResumeTypeName(typeCode) {
            const typeMap = {
                '0': '中文（简体）',
                '1': '英文',
                '2': '中英（前中后英）',
                '3': '英中（前英后中）',
                '4': '空',
                '10': '中文（繁体）'
            };
            return typeMap[String(typeCode)] || '未知类型';
        },
        getCollegeTypeName(code) {
            const map = {
                '0': '普通院校', '1': '985', '2': '211', '3': '港澳台院校',
                '4': '海外院校', '5': '中学', '6': '职业教育', '7': '培训机构'
            };
            return map[code] || '未知类型';
        },

        enablePolishMode() {
            this.showPolish = true;
        },
        async polishSection(section) {
            const prompt = `请对以下简历内容进行语言润色优化，提升表达的专业性、清晰度和逻辑性，保留原意，无需扩写内容。请仅输出润色建议，而非直接改写文本。\n\n内容如下：${section.content}`;
            const url = await this.getWebsocketUrl();
            const ws = new WebSocket(url);
            let result = '';

            ws.onopen = () => {
                const params = {
                    header: {
                        app_id: this.appId,
                        uid: "resume-polish-uid"
                    },
                    parameter: {
                        chat: {
                            domain: "generalv3.5",
                            temperature: 0.5,
                            max_tokens: 1024
                        }
                    },
                    payload: {
                        message: {
                            text: [{ role: 'user', content: prompt }]
                        }
                    }
                };
                ws.send(JSON.stringify(params));
            };

            ws.onmessage = (e) => {
                const json = JSON.parse(e.data);

                // 修改为兼容语法
                if (json.payload && json.payload.choices && json.payload.choices.text && json.payload.choices.text[0] && json.payload.choices.text[0].content) {
                    result += json.payload.choices.text[0].content;
                }
                if (json.header.status === 2) {
                    ws.close();
                    section.suggestion = result.trim().replace(/^```(json)?/, '').replace(/```$/, '');
                }
            };

            ws.onerror = () => {
                this.$message.error('润色建议请求失败');
            };
        },
        refineSection(type, index, content) {
            this.$set(this.refinementLoading[type], index, true);
            // 改进后的 prompt：明确要求输出为分段文本，每段前缩进两个空格，段落之间空一行
            const prompt = `请对以下简历内容进行语言润色优化，要求输出为三列表格形式，每条建议包含：
1. 原文（保持原始文本内容片段）
2. 润色建议（优化后的简洁专业表述）
3. 理由/效果（简要说明优化带来的改进，如更清晰、更正式、更专业）

请严格使用以下JSON数组格式返回，便于程序解析：
[
  {
    "原文": "原始文本",
    "润色建议": "优化后的文本",
    "理由/效果": "说明优化效果"
  },
  ...
]

不要输出除JSON之外的任何内容。
原始文本，优化后的文本和说明优化效果中不允许出现任何引号。
限制最多输出6条建议，确保每条建议简洁明了，避免冗长。请勿对内容进行扩展或添加新的信息，仅对现有文本进行优化。不要对同一句原文进行重复建议。
内容如下：${content}`;


            this.getWebsocketUrl().then(url => {
                const ws = new WebSocket(url);
                let result = '';

                ws.onopen = () => {
                    const params = {
                        header: {
                            app_id: this.appId,
                            uid: "resume-polish-uid"
                        },
                        parameter: {
                            chat: {
                                domain: "generalv3.5",
                                temperature: 0.5,
                                max_tokens: 1024
                            }
                        },
                        payload: {
                            message: {
                                text: [{ role: 'user', content: prompt }]
                            }
                        }
                    };
                    ws.send(JSON.stringify(params));
                };

                ws.onmessage = (e) => {
                    const json = JSON.parse(e.data);
                    if (
                        json.payload &&
                        json.payload.choices &&
                        json.payload.choices.text &&
                        json.payload.choices.text[0] &&
                        json.payload.choices.text[0].content
                    ) {
                        result += json.payload.choices.text[0].content;
                    }

                    if (json.header.status === 2) {
                        ws.close();

                        // 1. 去掉 Markdown 代码块
                        let cleaned = result
                            .replace(/^```(?:json)?\s*/i, '')
                            .replace(/\s*```$/, '')
                            .trim();

                        // 2. 从后往前截断到第一个合法的 JSON 数组
                        //    防止模型在末尾追加多余文字
                        const lastArrEnd = cleaned.lastIndexOf(']');
                        if (lastArrEnd > 0) cleaned = cleaned.slice(0, lastArrEnd + 1);

                        // 3. 统一中英文引号并尝试解析
                        cleaned = cleaned
                            .replace(/[“”]/g, '"')
                            .replace(/[‘’]/g, "'")
                            .replace(/,\s*}/g, '}')
                            .replace(/,\s*]/g, ']');

                        try {
                            const parsed = JSON.parse(cleaned);
                            this.$set(this.refinementResults[type], index, parsed);
                        } catch (err) {
                            console.error('解析润色结果失败:', err, cleaned);
                            this.$message.error('AI 返回格式异常，请稍后重试');
                        }

                        this.$set(this.refinementLoading[type], index, false);
                    }
                };

                ws.onerror = () => {
                    this.$message.error('润色建议请求失败');
                    this.$set(this.refinementLoading[type], index, false);
                };
            });
        },



        getWebsocketUrl() {
            return new Promise((resolve, reject) => {
                try {
                    const host = this.wsHost;
                    const path = "/v3.5/chat";
                    const date = new Date().toUTCString();
                    const algorithm = "hmac-sha256";
                    const headers = "host date request-line";
                    const signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${path} HTTP/1.1`;
                    const signatureSha = CryptoJS.HmacSHA256(signatureOrigin, this.apiSecret);
                    const signature = CryptoJS.enc.Base64.stringify(signatureSha);
                    const authorizationOrigin = `api_key=\"${this.apiKey}\", algorithm=\"${algorithm}\", headers=\"${headers}\", signature=\"${signature}\"`;
                    const authorization = btoa(authorizationOrigin);
                    const url = `wss://${host}${path}?authorization=${authorization}&date=${date}&host=${host}`;
                    resolve(url);
                } catch (e) {
                    reject(e);
                }
            });
        }
    }
}

</script>

<style scoped>
.refinement-card {
    border-radius: 8px;
    padding: 10px 12px;
    color: #0063A8;
    font-size: 14px;
    line-height: 1.5;
    white-space: pre-wrap;
}

.resume-container {
    background-color: #fff;
    width: 100%;
    padding: 20px;
    max-width: 960px;
    margin: auto;
    font-family: "Times New Roman", serif;
    line-height: 1.5;
}

.user-info {
    display: flex;
    flex-direction: row;
    align-items: center;
    margin-bottom: 20px;
}

.box-card {
    border-radius: 6px;
    padding: 12px 16px;
    background-color: white;
}

.avatar-box {
    margin-right: 20px;
    height: 100%;
    aspect-ratio: 5 / 7;
    background-color: aliceblue;
}

.info-box h2 {
    margin: 0;
    font-weight: bold;
    display: flex;
    flex-direction: column;
}

.tags {
    margin-top: 10px;
    display: flex;
    flex-direction: row;
    gap: 5px;
}

.project-block {
    margin-top: 10px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.responsibility-list {
    padding-left: 1.5em;
    /* 左边缩进整个列表 */
    margin: 4px 0 8px 0;
    line-height: 1.5;
}

.responsibility-list li {
    line-height: 1.2;
    text-indent: 0;
    /* 默认不要缩进第一行，统一由 padding 控制 */
    line-height: 1.5;
}

.dot {
    display: inline-block;
    width: 5px;
    height: 5px;
    background-color: rgb(255, 180, 54);
    border-radius: 50%;
    margin-right: 6px;
    position: relative;
    top: -3px;
}

.upload-demo {
    width: 100%;
    margin-top: 10px;
}
</style>
